{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "42bc8b74-b8e9-4cab-90ea-642868ab780b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-05-26T16:30:35.175481Z",
     "iopub.status.busy": "2025-05-26T16:30:35.175182Z",
     "iopub.status.idle": "2025-05-26T16:30:35.177746Z",
     "shell.execute_reply": "2025-05-26T16:30:35.177357Z",
     "shell.execute_reply.started": "2025-05-26T16:30:35.175465Z"
    },
    "tags": []
   },
   "source": [
    "# DAY 39"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf9e8b77",
   "metadata": {},
   "source": [
    "## 一、 图像数据的介绍\n",
    "### 1.1 灰度图像"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32423a41",
   "metadata": {},
   "source": [
    "从这里开始我们进入到了图像数据相关的部分，也是默认你有之前复试班计算机视觉相关的知识，但是一些基础的概念我仍然会提。\n",
    "\n",
    "\n",
    "昨天我们介绍了minist这个经典的手写数据集，作为图像数据，相较于结构化数据（表格数据）他的特点在于他每个样本的的形状并不是(特征数，)，而是(宽，高，通道数)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "855b420e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先继续之前的代码\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from torch.utils.data import DataLoader , Dataset # DataLoader 是 PyTorch 中用于加载数据的工具\n",
    "from torchvision import datasets, transforms # torchvision 是一个用于计算机视觉的库，datasets 和 transforms 是其中的模块\n",
    "import matplotlib.pyplot as plt\n",
    "# 设置随机种子，确保结果可复现\n",
    "torch.manual_seed(42)\n",
    "\n",
    "# 1. 数据预处理，该写法非常类似于管道pipeline\n",
    "# transforms 模块提供了一系列常用的图像预处理操作\n",
    "\n",
    "# 先归一化，再标准化\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),  # 转换为张量并归一化到[0,1]\n",
    "    transforms.Normalize((0.1307,), (0.3081,))  # MNIST数据集的均值和标准差，这个值很出名，所以直接使用\n",
    "])\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 2. 加载MNIST数据集，如果没有会自动下载\n",
    "train_dataset = datasets.MNIST(\n",
    "    root='./data',\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "test_dataset = datasets.MNIST(\n",
    "    root='./data',\n",
    "    train=False,\n",
    "    transform=transform\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "0303e0a0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Label: 7\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAGdCAYAAABU0qcqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuNSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/xnp5ZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAaNUlEQVR4nO3df0xV9/3H8Rf+4GotXIsIlztR0fpjqT+WOWXE1rWTiCwzWs2qtn9oYzQ6bKqss2PxR92W0NmlNV2c3dJF16TazsQfqUvsFAumG2qkGmO2EaHMH1NwmnEvYkUjn+8fpvfbq6g9eC9vuDwfyUm8954P992zG5473MshyTnnBABAB+thPQAAoHsiQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwEQv6wHu1NraqgsXLiglJUVJSUnW4wAAPHLOqampScFgUD163Ps8p9MF6MKFC8rOzrYeAwDwkM6dO6dBgwbd8/FO9yO4lJQU6xEAADHwoO/ncQvQpk2bNHToUPXp00e5ubk6evTo11rHj90AIDE86Pt5XAL04Ycfqri4WOvWrdNnn32m8ePHq6CgQJcuXYrH0wEAuiIXB5MmTXJFRUWR27du3XLBYNCVlpY+cG0oFHKS2NjY2Ni6+BYKhe77/T7mZ0A3btxQVVWV8vPzI/f16NFD+fn5qqysvGv/lpYWhcPhqA0AkPhiHqDLly/r1q1byszMjLo/MzNT9fX1d+1fWloqv98f2fgEHAB0D+afgispKVEoFIps586dsx4JANABYv57QOnp6erZs6caGhqi7m9oaFAgELhrf5/PJ5/PF+sxAACdXMzPgJKTkzVhwgSVlZVF7mttbVVZWZny8vJi/XQAgC4qLldCKC4u1oIFC/Sd73xHkyZN0saNG9Xc3KwXX3wxHk8HAOiC4hKguXPn6r///a/Wrl2r+vp6fetb39K+ffvu+mACAKD7SnLOOeshviocDsvv91uPAQB4SKFQSKmpqfd83PxTcACA7okAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJiIeYBee+01JSUlRW2jR4+O9dMAALq4XvH4ok888YQOHDjw/0/SKy5PAwDowuJShl69eikQCMTjSwMAEkRc3gM6ffq0gsGghg0bphdeeEFnz569574tLS0Kh8NRGwAg8cU8QLm5udq6dav27dunzZs3q66uTk899ZSampra3L+0tFR+vz+yZWdnx3okAEAnlOScc/F8gsbGRg0ZMkRvvvmmFi1adNfjLS0tamlpidwOh8NECAASQCgUUmpq6j0fj/unA/r376+RI0eqpqamzcd9Pp98Pl+8xwAAdDJx/z2gq1evqra2VllZWfF+KgBAFxLzAL3yyiuqqKjQv//9b/3973/Xs88+q549e2r+/PmxfioAQBcW8x/BnT9/XvPnz9eVK1c0cOBAPfnkkzp8+LAGDhwY66cCAHRhcf8QglfhcFh+v996DADAQ3rQhxC4FhwAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYCLuf5AOHetnP/uZ5zWrVq1q13O9/vrr7VqHxPSHP/zB85rGxsbYD4IugzMgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmEhyzjnrIb4qHA7L7/dbj9EpFBQUeF6zd+9ez2t69eKi6Hh47bmydXuu3v773//e8xrYCIVCSk1NvefjnAEBAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACa4CmUn9r///c/zmn379sVhEnQ3Q4YM8bxm7Nixnte89dZbntdUV1d7XlNeXu55DeKPMyAAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQXI+3Ejh496nnNjBkz4jAJupusrCzPa6qqqjrkefr16+d5DTonzoAAACYIEADAhOcAHTp0SDNmzFAwGFRSUpJ2794d9bhzTmvXrlVWVpb6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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 随机选择一张图片，可以重复运行，每次都会随机选择\n",
    "sample_idx = torch.randint(0, len(train_dataset), size=(1,)).item() # 随机选择一张图片的索引\n",
    "# len(train_dataset) 表示训练集的图片数量；size=(1,)表示返回一个索引；torch.randint() 函数用于生成一个指定范围内的随机数,item() 方法将张量转换为 Python 数字\n",
    "image, label = train_dataset[sample_idx] # 获取图片和标签\n",
    "# 可视化原始图像（需要反归一化）\n",
    "def imshow(img):\n",
    "    img = img * 0.3081 + 0.1307  # 反标准化\n",
    "    npimg = img.numpy()\n",
    "    plt.imshow(npimg[0], cmap='gray') # 显示灰度图像\n",
    "    plt.show()\n",
    "\n",
    "print(f\"Label: {label}\")\n",
    "imshow(image)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0b21607",
   "metadata": {},
   "source": [
    "上述是昨天的代码，我们介绍了图像数据的预处理，这是我们首次接触图像数据，他和之前的结构化数据有什么差异点呢？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7139834",
   "metadata": {},
   "source": [
    "结构化数据（如表格）的形状通常是 (样本数, 特征数)，例如 (1000, 5) 表示 1000 个样本，每个样本有 5 个特征。图像数据的形状更复杂，需要保留空间信息（高度、宽度、通道），因此不能直接用一维向量表示。其中颜色信息往往是最开始输入数据的通道的含义，因为每个颜色可以用红绿蓝三原色表示，因此一般输入数据的通道数是 3。\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "  | 维度索引 | 含义                 | 数值说明                  |  \n",
    "  |----------|----------------------|---------------------------|  \n",
    "  | `0`      | **通道数（Channels）**| `1` 表示这是一张灰度图（仅有一个颜色通道，如黑白照片）。<br>如果是彩色图（如RGB），通道数为 `3`。 |  \n",
    "  | `1`      | **高度（Height）**   | `28` 表示图像的垂直像素数为28像素。                     |  \n",
    "  | `2`      | **宽度（Width）**    | `28` 表示图像的水平像素数为28像素。                     |  \n",
    "\n",
    "MNIST 数据集是手写数字的 灰度图像，每个像素点的取值范围为 0-255（黑白程度），因此 通道数为 1。图像尺寸统一为 28×28 像素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "d4ee8985",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 28, 28])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 打印下图片的形状\n",
    "image.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8150ce89",
   "metadata": {},
   "source": [
    "### 1.2 彩色图像"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39679748",
   "metadata": {},
   "source": [
    "在 PyTorch 中，图像数据的形状通常遵循 (通道数, 高度, 宽度) 的格式（即 Channel First 格式），这与常见的 (高度, 宽度, 通道数)（Channel Last，如 NumPy 数组）不同。---注意顺序关系，\n",
    "\n",
    "注意点：\n",
    "1. 如果用matplotlib库来画图，需要转换下顺序，我们后续介绍\n",
    "2. 模型输入通常需要 批次维度（Batch Size），形状变为 (批次大小, 通道数, 高度, 宽度)。例如，批量输入 10 张 MNIST 图像时，形状为 (10, 1, 28, 28)。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "7002a404",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data\\cifar-10-python.tar.gz\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4e8b59cd35e6453c9bf2c10d3b200c98",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/170498071 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data\\cifar-10-python.tar.gz to ./data\n",
      "图像形状: torch.Size([3, 32, 32])\n",
      "图像类别: frog\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 打印一张彩色图像，用cifar-10数据集\n",
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# 设置随机种子确保结果可复现\n",
    "torch.manual_seed(42)\n",
    "# 定义数据预处理步骤\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),  # 转换为张量并归一化到[0,1]\n",
    "    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))  # 标准化处理\n",
    "])\n",
    "\n",
    "# 加载CIFAR-10训练集\n",
    "trainset = torchvision.datasets.CIFAR10(\n",
    "    root='./data',\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "# 创建数据加载器\n",
    "trainloader = torch.utils.data.DataLoader(\n",
    "    trainset,\n",
    "    batch_size=4,\n",
    "    shuffle=True\n",
    ")\n",
    "\n",
    "# CIFAR-10的10个类别\n",
    "classes = ('plane', 'car', 'bird', 'cat', 'deer', \n",
    "           'dog', 'frog', 'horse', 'ship', 'truck')\n",
    "\n",
    "# 随机选择一张图片\n",
    "sample_idx = torch.randint(0, len(trainset), size=(1,)).item()\n",
    "image, label = trainset[sample_idx]\n",
    "\n",
    "# 打印图片形状\n",
    "print(f\"图像形状: {image.shape}\")  # 输出: torch.Size([3, 32, 32])\n",
    "print(f\"图像类别: {classes[label]}\")\n",
    "\n",
    "# 定义图像显示函数（适用于CIFAR-10彩色图像）\n",
    "def imshow(img):\n",
    "    img = img / 2 + 0.5  # 反标准化处理，将图像范围从[-1,1]转回[0,1]\n",
    "    npimg = img.numpy()\n",
    "    plt.imshow(np.transpose(npimg, (1, 2, 0)))  # 调整维度顺序：(通道,高,宽) → (高,宽,通道)\n",
    "    plt.axis('off')  # 关闭坐标轴显示\n",
    "    plt.show()\n",
    "\n",
    "# 显示图像\n",
    "imshow(image)"
   ]
  },
  {
   "attachments": {
    "image.png": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "id": "002d17c0",
   "metadata": {},
   "source": [
    "注意，因为这里设计到图像的显示，所以就需要调整维度顺序：(通道,高,宽) → (高,宽,通道)\n",
    "\n",
    "![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a19a6633-cdb3-436f-b63e-c5e7651a19b9",
   "metadata": {},
   "source": [
    "介绍下超参数的优化 优化器\n",
    "\n",
    "优化手写数字问题 引出cnn\n",
    "\n",
    "如何计算显存一次性可以读取多少张\n",
    "\n",
    "随机种子"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "45dff9da",
   "metadata": {},
   "source": [
    "## 二、 图像相关的神经网络的定义\n",
    "\n",
    "考虑课程内容的推进，今日的内容只提定义，不涉及训练和测试过程"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "582de046",
   "metadata": {},
   "source": [
    "###  2.1 黑白图像模型的定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3f414303",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先归一化，再标准化\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),  # 转换为张量并归一化到[0,1]\n",
    "    transforms.Normalize((0.1307,), (0.3081,))  # MNIST数据集的均值和标准差，这个值很出名，所以直接使用\n",
    "])\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 2. 加载MNIST数据集，如果没有会自动下载\n",
    "train_dataset = datasets.MNIST(\n",
    "    root='./data',\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "test_dataset = datasets.MNIST(\n",
    "    root='./data',\n",
    "    train=False,\n",
    "    transform=transform\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f346c247",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "模型结构信息：\n",
      "----------------------------------------------------------------\n",
      "        Layer (type)               Output Shape         Param #\n",
      "================================================================\n",
      "           Flatten-1                  [-1, 784]               0\n",
      "            Linear-2                  [-1, 128]         100,480\n",
      "              ReLU-3                  [-1, 128]               0\n",
      "            Linear-4                   [-1, 10]           1,290\n",
      "================================================================\n",
      "Total params: 101,770\n",
      "Trainable params: 101,770\n",
      "Non-trainable params: 0\n",
      "----------------------------------------------------------------\n",
      "Input size (MB): 0.00\n",
      "Forward/backward pass size (MB): 0.01\n",
      "Params size (MB): 0.39\n",
      "Estimated Total Size (MB): 0.40\n",
      "----------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "# 定义两层MLP神经网络\n",
    "class MLP(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(MLP, self).__init__()\n",
    "        self.flatten = nn.Flatten()  # 将28x28的图像展平为784维向量\n",
    "        self.layer1 = nn.Linear(784, 128)  # 第一层：784个输入，128个神经元\n",
    "        self.relu = nn.ReLU()  # 激活函数\n",
    "        self.layer2 = nn.Linear(128, 10)  # 第二层：128个输入，10个输出（对应10个数字类别）\n",
    "        \n",
    "    def forward(self, x):\n",
    "        x = self.flatten(x)  # 展平图像\n",
    "        x = self.layer1(x)   # 第一层线性变换\n",
    "        x = self.relu(x)     # 应用ReLU激活函数\n",
    "        x = self.layer2(x)   # 第二层线性变换，输出logits\n",
    "        return x\n",
    "\n",
    "# 初始化模型\n",
    "model = MLP()\n",
    "\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "model = model.to(device)  # 将模型移至GPU（如果可用）\n",
    "\n",
    "from torchsummary import summary  # 导入torchsummary库\n",
    "print(\"\\n模型结构信息：\")\n",
    "summary(model, input_size=(1, 28, 28))  # 输入尺寸为MNIST图像尺寸"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b64698cb",
   "metadata": {},
   "source": [
    "我们关注和之前结构化MLP的差异\n",
    "1. 输入需要展平操作\n",
    "\n",
    "MLP 的输入层要求输入是一维向量，但 MNIST 图像是二维结构（28×28 像素），形状为 [1, 28, 28]（通道 × 高 × 宽）。nn.Flatten()展平操作 将二维图像 “拉成” 一维向量（784=28×28 个元素），使其符合全连接层的输入格式。\n",
    "\n",
    "其中不定义这个flatten方法，直接在前向传播的过程中用 x = x.view(-1, 28 * 28) 将图像展平为一维向量也可以实现\n",
    "\n",
    "2. 输入数据的尺寸包含了通道数input_size=(1, 28, 28)\n",
    "\n",
    "3. 参数的计算\n",
    "\n",
    "- 第一层 layer1（全连接层）\n",
    "\n",
    "权重参数：输入维度 × 输出维度 = 784 × 128 = 100,352\n",
    "\n",
    "偏置参数：输出维度 = 128\n",
    "\n",
    "合计：100,352 + 128 = 100,480\n",
    "\n",
    "- 第二层 layer2（全连接层）\n",
    "\n",
    "权重参数：输入维度 × 输出维度 = 128 × 10 = 1,280\n",
    "\n",
    "偏置参数：输出维度 = 10\n",
    "合计：1,280 + 10 = 1,290\n",
    "\n",
    "- 总参数：100,480（layer1） + 1,290（layer2） = 101,770"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cd244e0",
   "metadata": {},
   "source": [
    "### 2.2 彩色图像模型的定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "18ed06af",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "模型结构信息：\n",
      "----------------------------------------------------------------\n",
      "        Layer (type)               Output Shape         Param #\n",
      "================================================================\n",
      "           Flatten-1                 [-1, 3072]               0\n",
      "            Linear-2                  [-1, 128]         393,344\n",
      "              ReLU-3                  [-1, 128]               0\n",
      "            Linear-4                   [-1, 10]           1,290\n",
      "================================================================\n",
      "Total params: 394,634\n",
      "Trainable params: 394,634\n",
      "Non-trainable params: 0\n",
      "----------------------------------------------------------------\n",
      "Input size (MB): 0.01\n",
      "Forward/backward pass size (MB): 0.03\n",
      "Params size (MB): 1.51\n",
      "Estimated Total Size (MB): 1.54\n",
      "----------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "class MLP(nn.Module):\n",
    "    def __init__(self, input_size=3072, hidden_size=128, num_classes=10):\n",
    "        super(MLP, self).__init__()\n",
    "        # 展平层：将3×32×32的彩色图像转为一维向量\n",
    "        # 输入尺寸计算：3通道 × 32高 × 32宽 = 3072\n",
    "        self.flatten = nn.Flatten()\n",
    "        \n",
    "        # 全连接层\n",
    "        self.fc1 = nn.Linear(input_size, hidden_size)  # 第一层\n",
    "        self.relu = nn.ReLU()\n",
    "        self.fc2 = nn.Linear(hidden_size, num_classes)  # 输出层\n",
    "        \n",
    "    def forward(self, x):\n",
    "        x = self.flatten(x)  # 展平：[batch, 3, 32, 32] → [batch, 3072]\n",
    "        x = self.fc1(x)      # 线性变换：[batch, 3072] → [batch, 128]\n",
    "        x = self.relu(x)     # 激活函数\n",
    "        x = self.fc2(x)      # 输出层：[batch, 128] → [batch, 10]\n",
    "        return x\n",
    "\n",
    "# 初始化模型\n",
    "model = MLP()\n",
    "\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "model = model.to(device)  # 将模型移至GPU（如果可用）\n",
    "\n",
    "from torchsummary import summary  # 导入torchsummary库\n",
    "print(\"\\n模型结构信息：\")\n",
    "summary(model, input_size=(3, 32, 32))  # CIFAR-10 彩色图像（3×32×32）\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d234962",
   "metadata": {},
   "source": [
    "- 第一层 layer1（全连接层）\n",
    "\n",
    "权重参数：输入维度 × 输出维度 = 3072 × 128 = 393,216\n",
    "\n",
    "偏置参数：输出维度 = 128\n",
    "\n",
    "合计：393,216 + 128 = 393,344\n",
    "\n",
    "- 第二层 layer2（全连接层）\n",
    "\n",
    "权重参数：输入维度 × 输出维度 = 128 × 10 = 1,280\n",
    "\n",
    "偏置参数：输出维度 = 10\n",
    "\n",
    "合计：1,280 + 10 = 1,290\n",
    "\n",
    "- 总参数：393,344（layer1） + 1,290（layer2） = 394,634"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd41a7fc",
   "metadata": {},
   "source": [
    "### 2.3 模型定义与batchsize的关系"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d064973",
   "metadata": {},
   "source": [
    "实际定义中，输入图像还存在batchsize这一维度\n",
    "\n",
    "在 PyTorch 中，模型定义和输入尺寸的指定不依赖于 batch_size，无论设置多大的 batch_size，模型结构和输入尺寸的写法都是不变的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d70b3a0c",
   "metadata": {},
   "outputs": [],
   "source": [
    "class MLP(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.flatten = nn.Flatten() # nn.Flatten()会将每个样本的图像展平为 784 维向量，但保留 batch 维度。\n",
    "        self.layer1 = nn.Linear(784, 128)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.layer2 = nn.Linear(128, 10)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        x = self.flatten(x)  # 输入：[batch_size, 1, 28, 28] → [batch_size, 784]\n",
    "        x = self.layer1(x)   # [batch_size, 784] → [batch_size, 128]\n",
    "        x = self.relu(x)\n",
    "        x = self.layer2(x)   # [batch_size, 128] → [batch_size, 10]\n",
    "        return x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d8a08c1",
   "metadata": {},
   "source": [
    "PyTorch 模型会自动处理 batch 维度（即第一维），无论 batch_size 是多少，模型的计算逻辑都不变。batch_size 是在数据加载阶段定义的，与模型结构无关。\n",
    "\n",
    "summary(model, input_size=(1, 28, 28))中的input_size不包含 batch 维度，只需指定样本的形状（通道 × 高 × 宽）。\n",
    "\n",
    "\n",
    "\n",
    "总结：batch_size与模型定义的关系**\n",
    "| **组件**         | **是否涉及batch_size**                     | **示例代码**                                   |\n",
    "|------------------|-------------------------------------------|-----------------------------------------------|\n",
    "| **模型定义**     | ❌ 完全无关                               | `class MLP(nn.Module)` 中无需提及batch_size   |\n",
    "| **torchsummary** | ❌ 只需要样本形状（不含batch维度）         | `summary(model, input_size=(1, 28, 28))`      |\n",
    "| **DataLoader**   | ✅ 在此设置batch_size                      | `DataLoader(dataset, batch_size=64)`          |\n",
    "| **训练循环**     | ✅ 数据自动以batch形式输入模型             | `for data, target in train_loader: ...`       |\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42271e3e",
   "metadata": {},
   "source": [
    "## 三、显存占用的主要组成部分"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e99e5b6d-a841-43cf-9522-99f9dc04f465",
   "metadata": {},
   "source": [
    "昨天说到了在面对数据集过大的情况下，由于无法一次性将数据全部加入到显存中，所以采取了分批次加载这种方式。即一次只加载一部分数据，保证在显存的范围内。\n",
    "\n",
    "那么显存设置多少合适呢？如果设置的太小，那么每个batchsize的训练不足以发挥显卡的能力，浪费计算资源；如果设置的太大，会出现OOT（out of memory）\n",
    "\n",
    "\n",
    "\n",
    "显存一般被以下内容占用：\n",
    "1. 模型参数与梯度：模型的权重（Parameters）和对应的梯度（Gradients）会占用显存，尤其是深度神经网络（如 Transformer、ResNet 等），一个 1 亿参数的模型（如 BERT-base），单精度（float32）参数占用约 400MB（1e8×4Byte），加上梯度则翻倍至 800MB（每个权重参数都有其对应的梯度）。\n",
    "\n",
    "2. 部分优化器（如 Adam）会为每个参数存储动量（Momentum）和平方梯度（Square Gradient），进一步增加显存占用（通常为参数大小的 2-3 倍）\n",
    "\n",
    "3. 其他开销。\n",
    "\n",
    "[oom处理方案](https://cloud.tencent.com/developer/article/2519693)\n",
    "\n",
    "\n",
    "下面以手写数据集为例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "83d42d52",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch.utils.data import DataLoader\n",
    "\n",
    "# 定义训练集的数据加载器，并指定batch_size\n",
    "train_loader = DataLoader(\n",
    "    dataset=train_dataset,  # 加载的数据集\n",
    "    batch_size=64,          # 每次加载64张图像\n",
    "    shuffle=True            # 训练时打乱数据顺序\n",
    ")\n",
    "\n",
    "# 定义测试集的数据加载器（通常batch_size更大，减少测试时间）\n",
    "test_loader = DataLoader(\n",
    "    dataset=test_dataset,\n",
    "    batch_size=1000,\n",
    "    shuffle=False\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8593f286",
   "metadata": {},
   "source": [
    "手写数据集（MNIST）和当前 MLP 模型，显存占用的计算可以简化为以下几个部分。\n",
    "\n",
    "\n",
    "### 3.1 模型参数与梯度（FP32 精度）\n",
    "参数总量：101,770 个参数\n",
    "\n",
    "\n",
    "- **1字节（Byte）= 8位（bit）**，是计算机存储的最小寻址单位。  \n",
    "- 位（bit）是二进制数的最小单位（0或1），例如`0b1010`表示4位二进制数。\n",
    "- 1KB=1024字节；1MB=1024KB=1,048,576字节\n",
    "\n",
    "\n",
    " **常见数据类型的字节占用**  \n",
    "   | 数据类型       | 位数（bit） | 字节（Byte） | 数值范围（近似）         |\n",
    "   |----------------|-------------|--------------|--------------------------|\n",
    "   | `float32`（单精度浮点数） | 32          | 4            | ±1.7×10^38               |\n",
    "   | `float64`（双精度浮点数） | 64          | 8            | ±1.8×10^308              |\n",
    "   | `uint8`（无符号8位整数）  | 8           | 1            | 0~255                    |\n",
    "\n",
    "\n",
    " - MNIST数据集的原始图像像素值为**0-255的整数**（uint8类型，占1字节），表示灰度值（0=黑，255=白）。  \n",
    " - 但PyTorch的`transforms.ToTensor()`会将其**归一化到[0, 1]范围**，并转换为 `float32`类型（浮点型更适合神经网络计算）。\n",
    "\n",
    "\n",
    " **计算示例：单张MNIST图像的显存占用**\n",
    "1. **原始像素值（uint8，未转换时）**  \n",
    "   - 尺寸：28×28像素  \n",
    "   - 单像素占用：1字节（uint8）  \n",
    "   - 总占用：`28×28×1 = 784字节 ≈ 0.766 KB`  \n",
    "\n",
    "2. **转换为`float32`张量后**  \n",
    "   - 尺寸：`1×28×28`（通道×高×宽）  \n",
    "   - 单像素占用：4字节（float32）  \n",
    "   - 总占用：`1×28×28×4 = 3136字节 ≈ 3.06 KB`  \n",
    "\n",
    "\n",
    "单精度（float32）参数占用：101,770 × 4 Byte ≈ 403 KB\n",
    "\n",
    "梯度是损失函数对模型参数的导数（∂Loss/∂Weight），用于指示参数更新的方向和幅度。梯度是损失函数对模型参数的导数（∂Loss/∂Weight），用于指示参数更新的方向和幅度。因此在默认情况下，梯度的数据类型和数目与参数相同。\n",
    "\n",
    "梯度占用（反向传播时）：与参数相同，合计约 806 KB\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68e2a5cd",
   "metadata": {},
   "source": [
    "### 3.2 **优化器状态**\n",
    "####  SGD\n",
    "- SGD优化器**不存储额外动量**，因此无额外显存占用。  \n",
    "- SGD 随机梯度下降，最基础的优化器，直接沿梯度反方向更新参数。\n",
    "- 参数更新公式：w = w - learning_rate * gradient\n",
    "\n",
    "####  Adam\n",
    "- Adam优化器：自适应学习率优化器，结合了动量（Momentum）和梯度平方的指数移动平均。  \n",
    "- 每个参数存储动量（m）和平方梯度（v），占用约 `101,770 × 8 Byte ≈ 806 KB`  \n",
    "- 动量（m）：每个参数对应一个动量值，数据类型与参数相同（float32），占用 403 KB。\n",
    "- 梯度平方（v）：每个参数对应一个梯度平方值，数据类型与参数相同（float32），占用 403 KB。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b22f4d03",
   "metadata": {},
   "source": [
    "### 3.3 **数据批量（batch_size）的显存占用**\n",
    "- **单张图像尺寸**：`1×28×28`（通道×高×宽），归一化转换为张量后为`float32`类型  \n",
    "  - 单张图像显存占用：`1×28×28×4 Byte = 3,136 Byte ≈ 3 KB`  \n",
    "- **批量数据占用**：`batch_size × 单张图像占用`  \n",
    "  - 例如：`batch_size=64` 时，数据占用为 `64×3 KB ≈ 192 KB`  \n",
    "  - `batch_size=1024` 时，数据占用为 `1024×3 KB ≈ 3 MB` "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2d19981",
   "metadata": {},
   "source": [
    "### 3.4. **前向/反向传播中间变量**\n",
    "- 对于两层MLP，中间变量（如`layer1`的输出）占用较小：  \n",
    "  - `batch_size×128`维向量：`batch_size×128×4 Byte = batch_size×512 Byte`  \n",
    "  - 例如`batch_size=1024`时，中间变量约 `512 KB` "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8211bf9c",
   "metadata": {},
   "source": [
    "以SGD为例，此时其他参数占用固定，batchsize会影响显存占用\n",
    "\n",
    "| batch_size | 数据占用 | 中间变量 | 总显存占用（近似） |\n",
    "|------------|----------|----------|--------------------|\n",
    "| 64         | 192 KB   | 32 KB    | ~1 MB              |\n",
    "| 256        | 768 KB   | 128 KB   | ~1.7 MB            |\n",
    "| 1024       | 3 MB     | 512 KB   | ~4.5 MB            |\n",
    "| 4096       | 12 MB    | 2 MB     | ~15 MB             |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9c02b5b",
   "metadata": {},
   "source": [
    "在 PyTorch 中，在使用DataLoader加载数据时，如果不指定batch_size参数，默认值是1\n",
    "\n",
    "，即每次迭代返回一个样本。这与一次性使用全部数据进行训练是完全不同的概念。如果想要一次性使用全部数据进行训练，需要手动将batch_size设置为数据集的大小，但对于大型数据集，这样做通常会导致内存不足，因为一次性将所有数据加载到内存中可能会超出硬件的内存限制。\n",
    "\n",
    "大规模数据时，通常从16开始测试，然后逐渐增加，确保代码运行正常且不报错，直到出现 内存不足（OOM）报错 或训练效果下降，此时选择略小于该值的 batch_size。\n",
    "\n",
    "训练时候搭配 nvidia-smi 监控显存占用，合适的 batch_size = 硬件显存允许的最大值 × 0.8（预留安全空间），并通过训练效果验证调整。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "590c3554",
   "metadata": {},
   "source": [
    "补充说明： batchsize对于训练的影响\n",
    "\n",
    "在深度学习中，使用较大的 batch_size（批量大小）相比单样本训练（batch_size=1）有以下核心优势\n",
    "- 并行计算能力最大化，减小训练时间；且大幅减少更新次数\n",
    "- 梯度方向更准确，单样本训练的梯度仅基于单个数据点，可能包含大量噪声（尤其是数据分布不均或存在异常值时）。大 batch_size 的梯度是多个样本的**平均值**，能抵消单个样本的随机性，梯度方向更接近真实分布的 “全局最优方向”。会让训练过程更稳定，波动更小\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "| **场景**         | **计算过程**                                                                 | **参数更新方式**                     |\n",
    "|------------------|-----------------------------------------------------------------------------|------------------------------------|\n",
    "| **batch_size=1**  | 计算1个样本的损失 $ L_1 $ → 反向传播得到梯度 $ g_1 $                   | 直接用 $ g_1 $ 更新参数          |\n",
    "| **batch_size=12** | 计算12个样本的损失 $ L_1, L_2, ..., L_{12} $ → 分别求梯度 $ g_1, g_2, ..., g_{12} $ → 计算平均梯度 $ \\bar{g} = \\frac{g_1 + g_2 + ... + g_{12}}{12} $ | 用平均梯度 $ \\bar{g} $ 更新参数   |\n",
    "\n",
    "\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "yolov5",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
